/*
 * DesignAssignment1.asm
 *
 *  Created: 2/17/2014 7:16:50 PM
 *   Author: tawataob
 */ 

   ; Initializations
 .MACRO INITSTACK
       LDI R16, HIGH(RAMEND)
       OUT SPH, R16
       LDI R16, LOW(RAMEND)
       OUT SPL, R16
.ENDMACRO

INITSTACK
ldi r17, 0; flag for add/sub, 1 for add and 0 for subtract
ldi r30, 1; register loaded with a 1, used to toggle r17 (xor)
ldi r18, 100; STARTING NUMBER
ldi r19, 0 ; counter from 0 to 19
ldi r22, 0; offsetting value

; Generating 20 pseudo-random, non-sequential numbers.
; pseudo-code for generation:
; for(int i=1; i <= 20; i++) {
; if(AddFlag == True) { StartingValue += i; }
; else { StartingValue -= i; }
; AddFlag = !AddFlag; }

AddToList: ; adds generated numbers to the list (pushes them onto the stack)
push r18; push r18 onto the stack
inc r19; increase the counter
inc r22; increase the offset value
eor r17, r30; toggle add/sub flag
cpi r19, 20; compare counter to 20 to see if all 20 numbers have been generated
breq DoneGenerating
cpi r17, 1; check the add/sub flag to determine which operation to perform
breq AddOffset
sub r18, r22; subtract the offset value
rjmp AddToList; generate next number
AddOffset:
add r18, r22; add the offset value
rjmp AddToList; generate next number

DoneGenerating:
in r26, spl; preparing X register low byte
in r27, sph; preparing X register high byte
ldi r20, 0; initialize running sum for /3 numbers (high byte)
ldi r21, 0; initialize running sum for /3 numbers (low byte)
ldi r23, 0; initialize running sum for /5 numbers (high byte)
ldi r24, 0; initialize running sum for /5 numbers (low byte)

Check3Or5: ; sets up to check if each number is divisible by 3 or 5
cpi r19, 0; compare counter to 0 to see if all 20 numbers have been checked
breq Done
dec r19; decrease counter
inc r26; update stack pointer
ld r28, X; get value from stack
mov r29, r28; save value from stack in r29
rjmp Check3; check for divisibility by 3
Continue3Or5: ; Check3 will jump to here after completion in order to then check for divisibility by 5
ld r28, X; r28 will have been modified from Check3, so reload the value from the stack
rjmp Check5; check for divisibility by 5

Check3: ; checks for divisibility by 3
subi r28, 3; subtract 3 multiple times to check divisibility
;cpi r28, 0; checking if subtraction has passed 0
breq DivisibleBy3; if the result of the final subtraction was zero, then the number was divisible by 3
brmi Continue3Or5; if the result was negative, then the number was not divisible by 3
rjmp Check3; continue subtracting until r28 reaches 0
DivisibleBy3:
add r21, r29; if the number was divisible by 3, add it to the running sum
brcs CarryFor3; check for carry from the previous addtion
rjmp Continue3Or5; go back to checking

CarryFor3:
clc; clear the carry flag
inc r20; add the carry to the high byte
rjmp Continue3Or5; go back to checking

Check5: ; checks for divisibility by 5
subi r28, 5; subtract 5 multiple times to check divisibility
;cpi r28, 0; checking if subtraction has passed 0
breq DivisibleBy5; if the result of the final subtraction was zero, then the number was divisible by 5
brmi Check3Or5; if the result was negative, then the number was not divisible by 5
rjmp Check5; continue subtracting until r28 reaches 0
DivisibleBy5:
add r24, r29; if the number was divisible by 5, add it to the running sum
brcs CarryFor5; check for carry from the previous addtion
rjmp Check3Or5; go back to checking

CarryFor5:
clc; clear the carry flag
inc r23; add the carry to the high byte
rjmp Check3Or5; go back to checking

Done:
nop
rjmp Done; repeat continuously
;Divisible by 3 sum stored in R20:R21
;Divisible by 5 sum stored in R23:R24
